package com.xiaolei.libraryktx

import android.view.View
import androidx.collection.LruCache
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.RecyclerView
import com.xiaolei.library.Events.RecyclerViewItemTouchListener
import androidx.recyclerview.widget.DiffUtil
import com.xiaolei.library.Base.RecyclerAdapter

/**
 * RecyclerView的点击事件
 */
inline fun <reified T : RecyclerView> T.setOnItemClick(crossinline listener: (view: View, pos: Int) -> Unit)
{
    this.addOnItemTouchListener(object : RecyclerViewItemTouchListener(this)
    {
        override fun onItemDoubleClick(itemView: View, position: Int) = Unit
        override fun onItemLongPress(itemView: View, position: Int) = Unit
        override fun onItemClick(itemView: View, position: Int) = listener.invoke(itemView, position)
    })
}
/**
 * RecyclerView的长按事件
 */
inline fun <reified T : RecyclerView> T.setOnItemLongPress(crossinline listener: (view: View, pos: Int) -> Unit)
{
    this.addOnItemTouchListener(object : RecyclerViewItemTouchListener(this)
    {
        override fun onItemDoubleClick(itemView: View, position: Int) = Unit
        override fun onItemLongPress(itemView: View, position: Int) = listener.invoke(itemView, position)
        override fun onItemClick(itemView: View, position: Int)=Unit
    })
}

/**
 * RecyclerView的双击事件
 */
inline fun <reified T : RecyclerView> T.setOnItemDoubleClick(crossinline listener: (view: View, pos: Int) -> Unit)
{
    this.addOnItemTouchListener(object : RecyclerViewItemTouchListener(this)
    {
        override fun onItemDoubleClick(itemView: View, position: Int) = listener.invoke(itemView, position)
        override fun onItemLongPress(itemView: View, position: Int) = Unit
        override fun onItemClick(itemView: View, position: Int)=Unit
    })
}

class DiffCallBack<T : Any>(
    var newList: List<T>,
    var oldList: List<T>
) : DiffUtil.Callback()
{
    /**
     * 是不是同一个ID
     */
    var areIdSame: ((old: T, new: T) -> Boolean)? = null

    /**
     * 内容是否相同
     */
    var areContentSame: ((old: T, new: T) -> Boolean)? = null

    override fun getOldListSize() = oldList.size

    override fun getNewListSize() = newList.size

    override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean
    {
        val oldItem = oldList[oldItemPosition]
        val newItem = newList[newItemPosition]
        return areIdSame?.invoke(oldItem, newItem) ?: false
    }

    override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean
    {
        val oldItem = oldList[oldItemPosition]
        val newItem = newList[newItemPosition]
        return areContentSame?.invoke(oldItem, newItem) ?: false
    }
}


private val diffCache = LruCache<RecyclerAdapter<*>, DiffCallBack<Any>>(8)

private val <T : Any> RecyclerAdapter<T>.diffCallBack: DiffCallBack<Any>
    get() {
        val diff = diffCache[this] ?: DiffCallBack(emptyList(), emptyList())
        diffCache.put(this, diff)
        return diff
    }

/**
 * 差分更新
 */
fun <T : Any> RecyclerAdapter<T>.diffNotifyDataSetChanged(
    list: List<T>,
    rule: DiffCallBack<T>.() -> Unit
)
{
    rule.invoke(diffCallBack as DiffCallBack<T>)
    diffCallBack.newList = list
    diffCallBack.oldList = this.list
    val result = DiffUtil.calculateDiff(diffCallBack)
    this.list.clear()
    this.list.addAll(list)
    result.dispatchUpdatesTo(this)
}

fun <T : Diff> RecyclerAdapter<T>.diffNotifyDataSetChanged(list: List<T>)
{
    this.diffNotifyDataSetChanged(list) {
        areIdSame = { old, new ->
            old areSameItem new
        }
        areContentSame = { old, new ->
            old areSameContent new
        }
    }
}

interface Diff
{
    infix fun areSameItem(other: Diff): Boolean
    infix fun areSameContent(other: Diff): Boolean
}

/**
 * 禁用默认的更新动画
 */
inline fun <reified T : RecyclerView> T.disableChangeAnim()
{
    val animator = this.itemAnimator as? DefaultItemAnimator ?: return
    animator.supportsChangeAnimations = false
}